home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / dev / sun4.md / devZ8530.c < prev    next >
C/C++ Source or Header  |  1990-10-19  |  11KB  |  457 lines

  1. /* 
  2.  * devZ8530.c --
  3.  *
  4.  *    This file provides low-level procedures to manipulate the
  5.  *    Zilog 8530 Serial Communications Controller chip.  In particular,
  6.  *    the code in this file is enough to allow a Z8530 chip to be used
  7.  *    with devTty.c for terminals.
  8.  *
  9.  * Copyright 1989 Regents of the University of California
  10.  * Permission to use, copy, modify, and distribute this
  11.  * software and its documentation for any purpose and without
  12.  * fee is hereby granted, provided that the above copyright
  13.  * notice appear in all copies.  The University of California
  14.  * makes no representations about the suitability of this
  15.  * software for any purpose.  It is provided "as is" without
  16.  * express or implied warranty.
  17.  */
  18.  
  19. #ifndef lint
  20. static char rcsid[] = "$Header: /sprite/src/kernel/dev/sun3.md/RCS/devZ8530.c,v 9.4 90/10/19 15:48:56 rab Exp $ SPRITE (Berkeley)";
  21. #endif /* not lint */
  22.  
  23. #ifndef CLEAN_LOCK
  24. #define CLEAN_LOCK 1
  25. #endif
  26.  
  27. #include "sprite.h"
  28. #include "stdio.h"
  29. #include "mach.h"
  30. #include "sync.h"
  31. #include "z8530.h"
  32. #include <sgtty.h>
  33.  
  34. /*
  35.  * Spin-lock used for synchronization on all Z8530 device registers.
  36.  */
  37.  
  38. static Sync_Semaphore z8530Mutex = Sync_SemInitStatic("Dev:z8530Mutex");
  39.  
  40. /*
  41.  * Tables mapping sgttyb baud-rate values to actual integers.
  42.  */
  43.  
  44. static struct {
  45.     int sgttybVal;            /* Baud value from sgtyb. */
  46.     int baud;                /* Integer baud rate. */
  47. } baudMap[] = {
  48.     {B0, 0},
  49.     {B50, 50},
  50.     {B75, 75},
  51.     {B110, 110},
  52.     {B134, 134},
  53.     {B150, 150},
  54.     {B200, 200},
  55.     {B300, 300},
  56.     {B600, 600},
  57.     {B1200, 1200},
  58.     {B2400, 2400},
  59.     {B4800, 4800},
  60.     {B9600, 9600}, 
  61.     {-1, -1}
  62. };
  63.  
  64. /*
  65.  * Forward declarations to procedures defined in this file:
  66.  */
  67.  
  68. static int        Read();
  69. static void        Write();
  70.  
  71. /*
  72.  *----------------------------------------------------------------------
  73.  *
  74.  * DevZ8530Activate --
  75.  *
  76.  *    This procedure is invoked in order to "activate" one half of a
  77.  *    Z8530 chip.
  78.  *
  79.  * Results:
  80.  *    None.
  81.  *
  82.  * Side effects:
  83.  *    The channel is re-initialized and the receiver is started.
  84.  *
  85.  *----------------------------------------------------------------------
  86.  */
  87.  
  88. void
  89. DevZ8530Activate(ptr)
  90.     void *ptr;
  91. {
  92.     register DevZ8530 *zPtr = ptr;    /* Information about the device. */
  93.     int speed;
  94.  
  95.     MASTER_LOCK(&z8530Mutex);
  96.     if (zPtr->vector != 30) {
  97.     Mach_SetHandler(zPtr->vector, DevZ8530Interrupt, (ClientData) zPtr);
  98.     }
  99.     if (zPtr->flags & Z_CHANNEL_B) {
  100.     Write(zPtr->address, 9, WRITE9_RESET_CHAN_B);
  101.     } else {
  102.     Write(zPtr->address, 9, WRITE9_RESET_CHAN_A);
  103.     }
  104.     MACH_DELAY(10);
  105.     Write(zPtr->address, 2, zPtr->vector);
  106.     Write(zPtr->address, 4, WRITE4_PARITY_EVEN + WRITE4_1_STOP + 
  107.                 WRITE4_X16_CLK);
  108.     zPtr->wr3 &= ~WRITE3_RX_ENABLE;
  109.     Write(zPtr->address, 3, zPtr->wr3);
  110.     zPtr->wr5 &= ~(WRITE5_TX_ENABLE | WRITE5_BREAK);
  111.     Write(zPtr->address, 5, zPtr->wr5);
  112.     Write(zPtr->address, 11, WRITE11_TXCLK_BAUD + WRITE11_RXCLK_BAUD);
  113.     speed = ZILOG_SPEED(zPtr->baud);
  114.     Write(zPtr->address, 12, speed);
  115.     Write(zPtr->address, 13, speed >> 8);
  116.     Write(zPtr->address, 14, WRITE14_BAUD_FROM_PCLK);
  117.     zPtr->wr3 |= WRITE3_RX_ENABLE;
  118.     Write(zPtr->address, 3, zPtr->wr3);
  119.     zPtr->wr5 |= (WRITE5_TX_ENABLE | WRITE5_RTS | WRITE5_DTR);
  120.     Write(zPtr->address, 5, zPtr->wr5);
  121.     Write(zPtr->address, 14, WRITE14_BAUD_ENABLE + 
  122.                      WRITE14_BAUD_FROM_PCLK);
  123.     Write(zPtr->address, 0, WRITE0_RESET_ERRORS);
  124.     Write(zPtr->address, 0, WRITE0_RESET_STATUS);
  125.     Write(zPtr->address, 9, WRITE9_MASTER_IE); 
  126.     Write(zPtr->address, 1, WRITE1_RX_IE | WRITE1_TX_IE | WRITE1_EXT_IE); 
  127.     Write(zPtr->address, 0, WRITE0_CLEAR_INTR);
  128.     zPtr->oldRr0 = 0;
  129.     zPtr->flags &= ~Z_INACTIVE;
  130.     MASTER_UNLOCK(&z8530Mutex);
  131. }
  132.  
  133. /*
  134.  *----------------------------------------------------------------------
  135.  *
  136.  * DevZ8530RawProc --
  137.  *
  138.  *    This procedure is called back from the Td module as a raw
  139.  *    control procedure.
  140.  *
  141.  * Results:
  142.  *    The return value is the number of bytes returned to the caller
  143.  *    at outBuffer.
  144.  *
  145.  * Side effects:
  146.  *    Depends on the control operation.  Most likely effect is to
  147.  *    start transferring output data.
  148.  *
  149.  *----------------------------------------------------------------------
  150.  */
  151.  
  152. /* ARGSUSED */
  153. int
  154. DevZ8530RawProc(ptr, operation, inBufSize, inBuffer, outBufSize, outBuffer)
  155.     void *ptr;
  156.     int operation;        /* What to do:  TD_RAW_OUTPUT_READY etc. */
  157.     int inBufSize;        /* Size of input buffer for operation. */
  158.     char *inBuffer;        /* Input buffer. */
  159.     int outBufSize;        /* Size of output buffer for operation. */
  160.     char *outBuffer;        /* Output buffer. */
  161. {
  162.     int result = 0;
  163.     register DevZ8530 *zPtr = ptr;    /* Our information about device. */
  164.  
  165.     MASTER_LOCK(&z8530Mutex);
  166.     switch (operation) {
  167.     case TD_RAW_START_BREAK:
  168.         zPtr->wr5 |= WRITE5_BREAK;
  169.         Write(zPtr->address, 5, zPtr->wr5);
  170.         break;
  171.  
  172.     case TD_RAW_STOP_BREAK:
  173.         zPtr->wr5 &= ~WRITE5_BREAK;
  174.         Write(zPtr->address, 5, zPtr->wr5);
  175.         break;
  176.  
  177.     case TD_RAW_SET_DTR:
  178.         zPtr->wr5 |= WRITE5_DTR|WRITE5_RTS;
  179.         Write(zPtr->address, 5, zPtr->wr5);
  180.         break;
  181.  
  182.     case TD_RAW_CLEAR_DTR:
  183.         zPtr->wr5 &= ~(WRITE5_DTR|WRITE5_RTS);
  184.         Write(zPtr->address, 5, zPtr->wr5);
  185.         break;
  186.  
  187.     case TD_RAW_SHUTDOWN:
  188.         Write(zPtr->address, 1, 0);
  189.         MACH_DELAY(10);
  190.         zPtr->flags |= Z_INACTIVE;
  191.         break;
  192.  
  193.     case TD_RAW_OUTPUT_READY:
  194.         if (Read(zPtr->address, 0) & READ0_TX_READY) {
  195.         int c;
  196.  
  197.         c = (*zPtr->outputProc)(zPtr->outputData);
  198.         if (c != -1) {
  199.             Write(zPtr->address, 8, c);
  200.         }
  201.         }
  202.         break;
  203.  
  204.     case TD_RAW_FLUSH_OUTPUT:
  205.         while ((*zPtr->outputProc)(zPtr->outputData) != -1) {
  206.         /* do nothing */
  207.         }
  208.         break;
  209.  
  210.     case TD_RAW_FLOW_CHARS:
  211.         /* Ignore flow-control chars. */
  212.         break;
  213.  
  214.     case TD_RAW_SET_BAUD_RATE: {
  215.         int i, zilogSpeed;
  216.         Td_BaudRate *brPtr;
  217.  
  218.         /*
  219.          * Map the baud rate from an sgttyb constant to an actual
  220.          * number.  Return the value we actually set things to.
  221.          */
  222.  
  223.         brPtr = (Td_BaudRate *) inBuffer;
  224.         for (i = 0; baudMap[i].baud != -1; i++) {
  225.         if (baudMap[i].sgttybVal == brPtr->ospeed) {
  226.             zPtr->baud = baudMap[i].baud;
  227.             break;
  228.         }
  229.         }
  230.         zilogSpeed = ZILOG_SPEED(zPtr->baud);
  231.         Write(zPtr->address, 14, WRITE14_BAUD_FROM_PCLK);
  232.         Write(zPtr->address, 12, zilogSpeed);
  233.         Write(zPtr->address, 13, zilogSpeed >> 8);
  234.         Write(zPtr->address, 14, WRITE14_BAUD_ENABLE +
  235.             WRITE14_BAUD_FROM_PCLK);
  236.  
  237.         /*
  238.          * Fall through to next arm of case to return current
  239.          * settings.
  240.          */
  241.     }
  242.  
  243.     case TD_RAW_GET_BAUD_RATE: {
  244.         int i;
  245.         Td_BaudRate *brPtr;
  246.  
  247.         brPtr = (Td_BaudRate *) outBuffer;
  248.         if (outBufSize >= sizeof(Td_BaudRate)) {
  249.         for (i = 0; baudMap[i].baud != -1; i++) {
  250.             if (baudMap[i].baud == zPtr->baud) {
  251.             brPtr->ispeed = brPtr->ospeed = baudMap[i].sgttybVal;
  252.             result = sizeof(Td_BaudRate);
  253.             }
  254.         }
  255.         }
  256.         break;
  257.     }
  258.     }
  259.     MASTER_UNLOCK(&z8530Mutex);
  260.     return result;
  261. }
  262.  
  263. /*
  264.  *----------------------------------------------------------------------
  265.  *
  266.  * DevZ8530Interrupt --
  267.  *
  268.  *    This procedure is invoked at interrupt level to deal with
  269.  *    a channel of a Z5830 chip.
  270.  *
  271.  * Results:
  272.  *      Always returns TRUE.
  273.  *
  274.  * Side effects:
  275.  *    Input characters may be received, output characters may be
  276.  *    transmitted, and special conditions may be handled.
  277.  *
  278.  *----------------------------------------------------------------------
  279.  */
  280.  
  281. Boolean
  282. DevZ8530Interrupt(clientData)
  283.     ClientData    clientData; /* Information about the device. */
  284. {
  285.     register DevZ8530 *zPtr = (DevZ8530 *) clientData;    
  286.     int rr0, rr1, c;
  287.     int first = 1;
  288.  
  289.     MASTER_LOCK(&z8530Mutex);
  290.  
  291.     if (zPtr->flags & Z_INACTIVE) {
  292.     Write(zPtr->address, 1, 0);
  293.     Write(zPtr->address, 0, WRITE0_RESET_STATUS);
  294.     MASTER_UNLOCK(&z8530Mutex);
  295.     return TRUE;
  296.     }
  297.  
  298.     /*
  299.      * Check the input section of the channel.
  300.      */
  301.  
  302.     while (TRUE) {
  303.     rr0 = Read(zPtr->address, 0);
  304.     if (rr0 & READ0_BREAK) {
  305.         zPtr->flags |= Z_BREAK;
  306.     }
  307.     if (!(rr0 & READ0_RX_READY)) {
  308.         break;
  309.     }
  310.     c = Read(zPtr->address, 8);
  311.     if (first) {
  312.         first = 0;
  313.     } else {
  314.     }
  315.     if (zPtr->flags & Z_BREAK) {
  316.         zPtr->flags &= ~Z_BREAK;
  317.         if (c != 0) {
  318.         printf("Warning:  non-zero break character on %s\n",
  319.             zPtr->name);
  320.         } else {
  321.         c = DEV_TTY_BREAK;
  322.         }
  323.     }
  324.     (*zPtr->inputProc)(zPtr->inputData, c);
  325.     }
  326.  
  327.     rr1 = Read(zPtr->address, 1);
  328.     if (rr1 & (READ1_RX_OVERRUN|READ1_PARITY_ERROR|READ1_FRAMING_ERROR)) {
  329.     if (rr1 & READ1_RX_OVERRUN) {
  330.         printf("Warning: receiver overrun on %s\n", zPtr->name);
  331.     } else if (rr1 & READ1_PARITY_ERROR) {
  332.         printf("Warning: receiver parity error on %s\n", zPtr->name);
  333.     } else {
  334.         printf("Warning: receiver framing error on %s\n", zPtr->name);
  335.     }
  336.     Write(zPtr->address, 0, WRITE0_RESET_ERRORS);
  337.     }
  338.  
  339.     /*
  340.      * Check the output section of the channel.
  341.      */
  342.  
  343.     if (rr0 & READ0_TX_READY) {
  344.     c = (*zPtr->outputProc)(zPtr->outputData);
  345.     if (c == -1) {
  346.         Write(zPtr->address, 0, WRITE0_RESET_TX_INT);
  347.     } else {
  348.         Write(zPtr->address, 8, c);
  349.     }
  350.     }
  351.  
  352.     /*
  353.      * Reset status and interrupt bits.
  354.      */
  355.  
  356.     rr0 &= (READ0_DCD|READ0_CTS|READ0_BREAK);
  357.     if (zPtr->oldRr0 != rr0) {
  358.     Write(zPtr->address, 0, WRITE0_RESET_STATUS);
  359.     zPtr->oldRr0 = rr0;
  360.     }
  361.     Write(zPtr->address, 0, WRITE0_CLEAR_INTR);
  362.     MASTER_UNLOCK(&z8530Mutex);
  363.     return TRUE;
  364. }
  365.  
  366. /*
  367.  *----------------------------------------------------------------------
  368.  *
  369.  * Read --
  370.  *
  371.  *    Read a device register for the Z8530.
  372.  *
  373.  * Results:
  374.  *    The return value is the contents of the given register.
  375.  *
  376.  * Side effects:
  377.  *    None.
  378.  *
  379.  *----------------------------------------------------------------------
  380.  */
  381.  
  382. static int
  383. Read(devPtr, regNumber)
  384.     register volatile DevZ8530Device *devPtr;    /* Location of device
  385.                          * registers. */
  386.     int regNumber;                /* Number of register to
  387.                          * read. */
  388. {
  389.     devPtr->control = regNumber;
  390.     MACH_DELAY(4);
  391.     return devPtr->control;
  392. }
  393.  
  394. /*
  395.  *----------------------------------------------------------------------
  396.  *
  397.  * Write --
  398.  *
  399.  *    Write a device register for the Z8530.
  400.  *
  401.  * Results:
  402.  *    None.
  403.  *
  404.  * Side effects:
  405.  *    The given value is stored into the given register.
  406.  *
  407.  *----------------------------------------------------------------------
  408.  */
  409.  
  410. static void
  411. Write(devPtr, regNumber, value)
  412.     register volatile DevZ8530Device *devPtr;    /* Location of device
  413.                          * registers. */
  414.     int regNumber;                /* Number of register to
  415.                          * read. */
  416.     int value;                    /* Value to write in
  417.                          * register. */
  418. {
  419.     devPtr->control = regNumber;
  420.     MACH_DELAY(4);
  421.     devPtr->control = value;
  422. }
  423.  
  424. /*
  425.  *----------------------------------------------------------------------
  426.  *
  427.  * Dummy routines --
  428.  *
  429.  *    These procedures are needed in the interim while the new
  430.  *    tty driver is being brought up (6/89).  Once it's up, the dbg
  431.  *    module should be changed to make these procedures unnecessary.
  432.  *
  433.  * Results:
  434.  *    None.
  435.  *
  436.  * Side effects:
  437.  *    None.
  438.  *
  439.  *----------------------------------------------------------------------
  440.  */
  441.  
  442. void
  443. Dev_ZilogInit()
  444. {
  445. }
  446.  
  447. int
  448. Dev_ZilogReadReg()
  449. {
  450.     return 0;
  451. }
  452.  
  453. void
  454. Dev_ZilogWriteReg()
  455. {
  456. }
  457.